/**
 * 分布式条件类型（Distributive Conditional Type），也称 条件类型 的 分布式特性
 * 
 * 官方的解释：
 * 对于属于 裸类型参数 的检查类型，条件类型 会在 实例化时期 自动分发到 联合类型 上。
 * 
 * 分布式条件类型是 条件类型 在满足一定情况下会执行的逻辑，需要满足的条件：
 * 首先，类型参数 需要是一个 联合类型 。
 * 其次，类型参数 需要通过 泛型 参数的方式传入，而不能直接进行条件类型判断。
 * 最后，条件类型中的 泛型参数 不能被包裹。
 * 
 * 条件类型分布式特性 会产生的效果也很明显了，
 * 即将这个 联合类型 拆开来，每个分支分别进行一次条件类型判断，
 * 再将最后的结果合并起来如：
*/

//分布式条件类型
type Naked<T> = T extends boolean ? "Y" : "N";
// (number extends boolean ? "Y" : "N") | (boolean extends boolean ? "Y" : "N")
type Res3 = Naked<number | boolean>; // "N" | "Y"

//不符合分布式条件类型，因为 泛型参数被数组包裹
type Wrapped<T> = [T] extends [boolean] ? "Y" : "N";
type Res4 = Wrapped<number | boolean>; // "N"

//官方的解释中：裸类型参数，其实指的就是 泛型参数 是否完全裸露，
//上面使用 泛型参数被数组包裹 只是其中一种方式，比如这样也不属于 裸类型参数，也不符合分布式条件类型：
type NoDistribute<T> = T & {};
type WrappedA<T> = NoDistribute<T> extends boolean ? "Y" : "N";
type Res1 = WrappedA<number | boolean>; // "N"
type Res2 = WrappedA<true | false>; // "Y"
type Res5 = WrappedA<true | false | 599>; // "N"

/**
 * 在某些情况下，也会需要 包裹 泛型参数 来 禁用掉分布式特性。
 * 最常见的场景也许还是联合类型的判断，
 * 即不希望进行 联合类型成员 的 分布判断，
 * 而是希望 直接判断 这两个联合类型 的兼容性判断：
*/
type CompareUnion<T, U> = [T] extends [U] ? true : false;
type CompareRes1 = CompareUnion<1 | 2, 1 | 2 | 3>; // true
type CompareRes2 = CompareUnion<1 | 2, 1>; // false

/**
 * 另外一种情况则是，需要 包裹 泛型参数，来判断一个类型是否为 never 时：
 * 因为如果不包裹 never 通过 泛型参数 传入，会直接跳过判断
*/
type IsNever<T> = [T] extends [never] ? true : false;
type IsNeverRes1 = IsNever<never>; // true
type IsNeverRes2 = IsNever<"hanxuming">; // false

//不包裹 never 通过 泛型参数 传入，会直接跳过判断
type Tmp4<T> = T extends string ? 1 : 2;
type Tmp4Res = Tmp4<never>; // never

// never直接使用，仍然会进行判断
type Tmp3 = never extends string ? 1 : 2; // 1


/**
 * any 在 直接作为判断参数时 和 作为泛型参数时都会产生这一效果，返回一个 联合类型
*/
// 直接使用，返回联合类型
type Tmp1 = any extends string ? 1 : 2;  // 1 | 2
// 通过泛型参数传入，同样返回联合类型
type Tmp2<T> = T extends string ? 1 : 2;
type Tmp2Res = Tmp2<any>; // 1 | 2
// 但是如果判断条件是 any，那么仍然会进行判断
type Special1 = any extends any ? 1 : 2; // 1
type Special2<T> = T extends any ? 1 : 2;
type Special2Res = Special2<any>; // 1

/**
 * 在类型世界中联合类型就像是一个集合一样。
 * 通过使用分布式条件类型，能轻易地进行 集合之间的运算，比如交集：
*/
type Intersection<A, B> = A extends B ? A : never;
type IntersectionRes = Intersection<1 | 2 | 3, 2 | 3 | 4>; // 2 | 3







//export {}：解决“无法重新声明块范围变量”错误提示问题
export { }